<template>
    <div class="layout">
        <ToolbarPanel ref="toolbarRef" />
        <div class="container" :class="{ 'full-schedule-flow-wrapper': isFullScreen }">
            <!-- 左侧菜单 -->
            <Menu :graph="graph" ref="menuRef" @canvas-add-node="addNode" />
            <!-- 中间内容区 -->
            <div class="content" ref="canvasContainerRef">
                <!-- 挂载点 -->
                <div class="canvas" ref="canvasRef" @dragover.prevent.stop @contextmenu.stop.prevent />
                <!-- minimap -->
                <div class="minimap" ref="minimap"></div>
            </div>
            <!-- 右侧属性配置 -->
            <Props :isExtand="isExtand" />
        </div>
    </div>
</template>
<script>
import G6 from '@antv/g6';
import Menu from './components/menu/Index';
import Props from './components/props/Index';
import ResizeObserver from 'resize-observer-polyfill';
import debounce from 'lodash/debounce';
import registerFactory from './register-factory.js';
import utils from '@/utils/utils.js';
import Command from './plugins/command.js';
import Toolbar from './plugins/toolbar.js';
import ToolbarPanel from './components/toolbar-panel/Index';
export default {
    components: {
        Menu,
        Props,
        ToolbarPanel
    },
    props: {
        mode: {
            // graph的模式 default view edit
            type: String,
            default: 'edit'
        },
        data: {
            // graph画布渲染的数据
            type: Object,
            default: () => ({
                nodes: [
                    {
                        id: 'node1',
                        x: 100,
                        y: 200
                    },
                    {
                        id: 'node2',
                        x: 300,
                        y: 200
                    }
                ],
                edges: [
                    {
                        source: 'node1',
                        target: 'node2'
                    }
                ]
            })
        }
    },
    data() {
        return {
            graph: null,
            isExtand: false, // 是否展开属性配置抽屉
            isFullScreen: false, // 是否全屏
            cmdPlugin: null, // 命令插件
            defaultCanvasOption: {
                // 画布宽高
                width: 0,
                height: 0
            },
            canvasOffset: {
                x: 0,
                y: 0
            }
        };
    },
    mounted() {
        this.addEventListener();
        this.createG6();
        this.addObserver();
    },
    watch: {
        data(val) {
            if (this.graph?.cfg) {
                // 更新数据
                this.graph.changeData(val);
                // 清除画布选中态
                this.graph.emit('canvas:click');
                // 初始化命令
                if (this.cmdPlugin) {
                    this.cmdPlugin.initPlugin(this.graph);
                }
            }
        }
    },
    methods: {
        createG6() {
            // 注册自定义节点、边
            registerFactory(G6);
            // 插件
            const grid = new G6.Grid();
            const minimap = new G6.Minimap({
                size: [200, 100],
                container: this.$refs['minimap']
            });
            // 插件
            this.cmdPlugin = new Command();
            const toolbar = new Toolbar({ container: this.$refs['toolbarRef'].$el });
            console.log(444, toolbar);
            const plugins = [this.cmdPlugin, toolbar];
            // 画布
            const canvasMap = this.$refs['canvasRef'];
            this.graph = new G6.Graph({
                plugins: [grid, minimap, ...plugins],
                container: canvasMap,
                width: 600,
                height: 400,
                animate: true, // 全局变化时是否使用动画过渡
                animateCfg: {
                    duration: 500,
                    easing: 'easeLinear'
                },
                // 编辑模式下行为
                modes: {
                    edit: [
                        'drag-canvas', // 内置-拖拽画布
                        'drag-node',   // 内置-拖拽节点
                        'zoom-canvas', // 内置-缩放画布
                        'brush-select',// 内置-手动框选
                        'canvas-event',// 自定义-画布事件
                        'delete-item',
                        'select-node',
                        'hover-node',
                        'active-edge'
                    ]
                },
                // 默认节点配置
                defaultNode: {
                    type: 'rect-node',
                    style: {
                        radius: 10
                    },
                    labelCfg: {
                        fontSize: 12
                    }
                },
                // 默认边配置
                defaultEdge: {
                    type: 'polyline-edge',
                    style: {
                        radius: 5,
                        offset: 15,
                        stroke: '#aabb7c3',
                        lineAppendWidth: 10,
                        endArrow: true
                    }
                },
                // 全局样式
                nodeStateStyles: {
                    'nodeState:default': {
                        lineWidth: 1,
                        fill: '#fff',
                        stroke: '#1890FF',
                        opacity: 1
                    },
                    'nodeState:hover': {
                        lineWidth: 2,
                        fill: '#d5f1fd',
                        opacity: 0.8
                    },
                    'nodeState:selected': {
                        fill: '#caebf9',
                        stroke: '#1890FF',
                        opacity: 0.9
                    }
                },
                edgeStateStyles: {
                    'edgeState:default': {
                        stroke: 'aabb7c3'
                    },
                    'edgeState:hover': {
                        animate: true,
                        animationType: 'dash',
                        stroke: '#1890FF'
                    },
                    'edgeState:selected': {
                        stroke: '#1890FF'
                    }
                }
            });
            // 设置graph模式
            this.graph.setMode(this.mode);
            // 设置自适应比例
            this.graph.fitView = true;
            // 初始化canvas事件
            this.initEvents();
        },
        initEvents() {
            const graph = this.graph;
            // 点击画布，隐藏contextMenu
            graph.on('on-canvas-click', e => {
                this.$emit('contextMenuEvent', { graph: graph, isShow: false });
            });
            // 拖拽画布后，修改画布偏移量
            graph.on('on-canvas-dragend', e => {
                this.canvasOffset = {
                    x: e.dx,
                    y: e.dy
                }
            });
            // 节点点击
            graph.on('after-node-selected', e => {
                if (!e.item) return;
                
            });
            // 移除节点
            graph.on('before-node-removed', ({ target, targetModel, callback }) => {
                console.log('移除节点', target, targetModel);
                callback(true)
            });
            // 移除边
            graph.on('before-edge-removed', ({ target, targetModel, callback }) => {
                console.log('移除边', target, targetModel);
                callback(true)
            });
            // 创建一条连线
            graph.on('before-edge-add', ({ source, target, sourceAnchor, targetAnchor }) => {
                const edges = this.graph.getEdges();
                const edgeId = utils.maxId(edges, 'edge');
                setTimeout(() => {
                    // 创建连线，返回边对象
                    let edgeObj = this.graph.addItem('edge', {
                        id: edgeId,
                        source: source.get('id'),
                        target: target.get('id'),
                        sourceAnchor,
                        targetAnchor
                    });
                    // 边对象数据
                    let model = edgeObj.getModel();
                    // 获取来源组件id
                    let sourceComponentId = '';
                    const sourceModel = source.getModel();
                    if (sourceModel.data && sourceModel.data.id) {
                        sourceComponentId = sourceModel.data.id;
                    }
                    // 获取目标组件id
                    let targetComponentId = ''; //目标组件id
                    const targetModel = target.getModel();
                    if (targetModel.data && targetModel.data.id) {
                        targetComponentId = targetModel.data.id;
                    }
                    model.fromComponentId = sourceComponentId;
                    model.toComponentId = targetComponentId;
                }, 100);
            });
            // 选中连接线
            graph.on('after-edge-selected', e => {
                console.log('选中连线');
            });
            // contextMenu
            graph.on('on-editor-contextmenu', data => {
                const mode = graph.getCurrentMode();
                if (mode === 'edit') {
                    this.$bus.emit('contextMenuEvent', { graph: this.graph, isShow: true, ...data });
                }
            });
        },
        // 添加节点
        addNode(e, nodeModel) {
            nodeModel = JSON.parse(JSON.stringify(nodeModel));
            console.log(222, nodeModel);
            const offsetWidth = document.body.clientWidth - this.defaultCanvasOption.width;
            const offsetHeight = document.body.clientHeight - this.defaultCanvasOption.height;
            const nodes = this.graph.getNodes();
            const nodeId = utils.maxId(nodes, 'node');
            nodeModel.id = nodeId;
            const model = {
                id: nodeId,
                text: 'node',
                type: nodeModel.shape, // 形状
                componentType: nodeModel.componentType,
                data: nodeModel,
                label: nodeModel.componentName ?? '',
                x: e.clientX - this.canvasOffset.x - offsetWidth, // 位置x坐标
                y: e.clientY - this.canvasOffset.y - offsetHeight // 位置y坐标
            };
            
            this.graph.addItem('node', model);
        },
        // 屏幕缩放调整画布宽高
        addObserver() {
            this.resizeObserver = new ResizeObserver(entries => {
                const { width = 0, height = 0 } = (entries[0] && entries[0].contentRect) || {};
                debounce(() => {
                    if (width !== this.defaultCanvasOption.width || height !== this.defaultCanvasOption.height) {
                        if (this.graph?.cfg) {
                            this.graph.changeSize(width, height);
                        }
                        this.defaultCanvasOption = { width, height };
                    }
                }, 1000)();
            });
            this.resizeObserver.observe(this.$refs.canvasContainerRef);
        },
        // 事件监听
        addEventListener() {
            const _this = this;
            // 全屏
            _this.$bus.on('fullScreenEvent', isFull => {
                _this.isFullScreen = isFull;
            });
            // 组合
            _this.$bus.on('groupFlowEvent', () => {
                console.log('组合');
            });
            // 取消组合
            _this.$bus.on('ungroupFlowEvent', () => {
                console.log('取消组合');
            });
            // 保存
            _this.$bus.on('saveFlowEvent', () => {
                console.log('保存');
            });
        },
        // 移除事件监听
        removeEventListener() {
            this.$bus.off('fullScreenEvent');
            this.$bus.off('groupFlowEvent');
            this.$bus.off('ungroupFlowEvent');
            this.$bus.off('saveFlowEvent');
        }
    },
    beforeDestroy() {
        this.removeEventListener();
        if (this.graph?.destroyed) {
            this.graph.destroyed();
        }
    }
};
</script>
<style lang="scss" src="./Index.scss" scoped></style>
